package it.softphone.commons.util.web;


import it.softphone.commons.util.Base64;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;



/**
 * 
 * 
 * @author softphone
 * 
 * @see java.net.Authenticator
 */
public class BasicAuthcUtil {

	public static final String AUTHORIZATION_HEADER = "Authorization";

	private BasicAuthcUtil() {}
	
	/**
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public static String getEncoding( String username, String password ) {
		 
		String userPassword = String.format( "%s:%s", username, password);

		 String encoding = new String(Base64.encodeBytes(userPassword.getBytes()));
		
		 return encoding;
	}
	
	/**
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public static Map.Entry<String,String> getHeaderValue( final String username, final String password ) {
		 
		return new Map.Entry<String,String>() {

			public String getKey() {
				return AUTHORIZATION_HEADER;
			}

			public String getValue() {
				return String.format( "Basic %s", getEncoding(username, password));
			}

			public String setValue(String value) {
				throw new UnsupportedOperationException();
			}
		};
		
		

	}
	
	/**
	 * <pre>
	 * 
	 * This method has been deprecated use java.net.Authenticator instead
	 * 
	 * </pre>
	 * 
	 * @param url
	 * @param username
	 * @param password
	 * @throws IOException 
	 */
	@Deprecated
	public static void authenticate( final java.net.URL url, final String username, final String password, final AuthcCallback callback ) throws IOException {
		if( url == null ) throw new IllegalArgumentException( "param url is null");
		if( username == null ) throw new IllegalArgumentException( "param login is null");
		if( password == null ) throw new IllegalArgumentException( "param username is null");
		if( callback == null ) throw new IllegalArgumentException( "param callabck is null");
		
		final String encoding = getEncoding( username, password );
		
		
		new Thread( new Runnable() {
			public void run() {

				try {
					URLConnection uc = url.openConnection();
					uc.setRequestProperty (AUTHORIZATION_HEADER, "Basic " + encoding);
					
					InputStream content = (InputStream)uc.getInputStream();
					
					callback.onSuccess(new InputStreamReader (content));
					
					content.close();
					
				} catch (IOException e) {
					callback.onError(e);
				}
				
				
			}
		}, 
		"AUTHENTICATE").start();
		
		
	}
	
	/**
	 * send POST request request
	 * 
	 * <pre>
	 * 
	 * This method has been deprecated use java.net.Authenticator instead
	 * 
	 * </pre>
	 *  
	 * @param url
	 * @param parameters
	 * @param username
	 * @param password
	 * @param callback
	 * @throws IOException
	 */
	@Deprecated
	public static void authenticate( final java.net.URL url, final java.util.Map<String,String> parameters, final String username, final String password, final AuthcCallback callback ) throws IOException {
		if( url == null ) throw new IllegalArgumentException( "param url is null");
		if( username == null ) throw new IllegalArgumentException( "param login is null");
		if( password == null ) throw new IllegalArgumentException( "param username is null");
		if( callback == null ) throw new IllegalArgumentException( "param callabck is null");
		
		final String encoding = getEncoding( username, password );
		
		
		new Thread( new Runnable() {
			public void run() {

				try {
					URLConnection uc = url.openConnection();
				    // Let the run-time system (RTS) know that we want input.
				    uc.setDoInput (true);
				    // Let the RTS know that we want to do output.
				    uc.setDoOutput (true);
				    // No caching, we want the real thing.
				    uc.setUseCaches (false);
				    // Specify the content type.
				    uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

					uc.setRequestProperty (AUTHORIZATION_HEADER, "Basic " + encoding);
					
				    //
					// WRITE TO OUTPUT STREAM
				    //
					
					if( parameters !=null ) {
						
						StringBuilder sw = new StringBuilder();
						
						for( Map.Entry<String, String> e : parameters.entrySet() ) {
							
							sw.append( e.getKey() ).append( '=' ).append( URLEncoder.encode(e.getValue(), "UTF-8")).append('&');
							
						}
						
						DataOutputStream out = new DataOutputStream (uc.getOutputStream ());
					    out.writeBytes( sw.toString() );
					    out.flush ();
					    out.close ();
					    
					}
				    //
					// GET INPUT STREAM
				    //
				    
					InputStream content = (InputStream)uc.getInputStream();

					callback.onSuccess(new InputStreamReader (content));
					
					content.close();
					
				} catch (IOException e) {
					callback.onError(e);
				}
				
				
			}
		}, 
		"AUTHENTICATE").start();
		
		
	}
	

}
